package com.meida.module.bus.provider.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.constants.CommonConstants;
import com.meida.common.enums.OrderStatusEnum;
import com.meida.common.enums.PayStatusEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.DateUtils;
import com.meida.common.utils.OrderNoUtil;
import com.meida.common.utils.RedisUtils;
import com.meida.module.bus.client.entity.VipType;
import com.meida.module.bus.provider.service.*;
import com.meida.module.order.client.entity.OrderDetails;
import com.meida.module.order.client.entity.OrderInfo;
import com.meida.module.order.provider.mapper.OrderDetailsMapper;
import com.meida.module.order.provider.mapper.OrderInfoMapper;
import com.meida.module.order.provider.service.OrderDetailsService;
import com.meida.module.product.client.entity.ProdProduct;
import com.meida.module.product.provider.service.ProdProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;

/**
 * 订单表接口实现类
 *
 * @author flyme
 * @date 2022-06-23
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BusOrderInfoServiceImpl extends BaseServiceImpl<OrderInfoMapper, OrderInfo> implements BusOrderInfoService {


    @Resource
    private OrderDetailsService orderDetailsService;

    @Resource
    private OrderNoUtil orderNoUtil;

    @Resource
    private ProdProductService productService;

    @Resource
    private OrderDetailsMapper detailsMapper;

    @Resource
    private BusProductService busProductService;

    @Resource
    private VipTypeService vipTypeService;

    @Resource
    private BusVipTypeService busVipTypeService;

    @Resource
    private AppUserExtraService appUserService;

    @Resource
    private RedisUtils redisUtils;

    @Autowired
    private RebateLogicService rebateLogicService;

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<OrderInfo> cq, OrderInfo orderInfo, EntityMap requestMap) {
        cq.select(OrderInfo.class, new String[]{"orderId", "parentId", "shopId", "companyId", "orderTitle", "orderNo", "userCouponId", "freightAmount", "totalAmount", "couponAmount", "discountAmount", "productCount", "payAmount", "selfState", "parentOrder", "orderState", "payState", "payType", "createTime"});
        cq.eq(OrderInfo.class, "showState", CommonConstants.INT_1);
        cq.like(OrderInfo.class, "orderNo");
        Integer orderState = requestMap.getInt("orderState", 0);
        if (!orderState.equals(0)) {
            cq.likeRight(true, "orderState", orderState);
        }

        cq.ge(OrderInfo.class, "createTime", cq.getParams("beginDate"));
        cq.le(OrderInfo.class, "createTime", cq.getParams("endDate"));
        cq.orderByDesc("orderinfo.createTime");
        return ResultBody.ok();
    }


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody beforeAdd(CriteriaSave cs, OrderInfo orderInfo, EntityMap extra) {
        //订单总金额
        BigDecimal totalAmount = new BigDecimal("0");
        //实付金额
        BigDecimal payAmount = new BigDecimal("0");
        Long userId = OpenHelper.getUserId();
        if (ObjectUtil.isNotNull(cs.getParams("productId"))) {

            String productId = cs.getParams("productId");
            ProdProduct product = this.productService.getById(productId);
            ApiAssert.isNotEmpty("商品不存在", product);
            totalAmount = product.getProductPrice();
            payAmount = product.getProductPrice();
            orderInfo.setOrderTitle(product.getProductName());
            orderInfo.setOrderType(1);
        }
        if (ObjectUtil.isNotNull(cs.getParams("vipTypeId"))) {
            VipType vipType = this.vipTypeService.getById(cs.getParams("vipTypeId"));
            ApiAssert.isNotEmpty("商品不存在", vipType);
            totalAmount = vipType.getPrePrice();
            payAmount = vipType.getPrePrice();
            orderInfo.setOrderTitle(vipType.getVipName());
            orderInfo.setOrderType(2);
        }
        ApiAssert.gezero("商品价格设置错误", payAmount);
        this.initOrderInfo(orderInfo, payAmount, userId, totalAmount);
        return ResultBody.ok();
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody afterAdd(CriteriaSave cs, OrderInfo orderInfo, EntityMap extra) {
        OrderDetails orderDetails = null;
        if (ObjectUtil.isNotNull(cs.getParams("productId"))) {
            ProdProduct product = this.productService.getById(cs.getParams("productId"));
            orderDetails = this.getOrderDetails(null, orderInfo, product);
            // TODO 测试 不走付款计算佣金
            //EntityMap payUser = appUserService.getAppUserVipInfo(OpenHelper.getUserId());
            //EntityMap superiorUser = ObjectUtil.isEmpty(payUser.get("inviterId")) ? null : appUserService.getAppUserVipInfo(payUser.getLong("inviterId"));
            //rebateLogicService.buyCommodity(orderInfo, product, payUser, superiorUser);
        }
        if (ObjectUtil.isNotNull(cs.getParams("vipTypeId"))) {
            //VipType vipType = this.vipTypeService.getById(cs.getParams("vipTypeId"));
            //orderDetails = getOrderDetails(orderInfo, vipType);
            //// TODO 测试 不走付款计算佣金
            //busVipTypeService.buyVip(vipType.getVipTypeId(), OpenHelper.getUserId());
        }
        orderDetailsService.save(orderDetails);

        // 自动取消订单设置key
        EntityMap map = redisUtils.getConfigMap("ORDER_INVALID_CONFIG");
        int invalid = map.getInt("orderInvalid", 30);
        redisUtils.set("unpaidOrder:" + orderInfo.getOrderId(), orderInfo.getOrderId(), invalid * 60);

        return ResultBody.ok("订单创建成功", orderInfo);
    }

    private OrderDetails getOrderDetails(OrderInfo orderInfo, VipType vipType) {
        Long userId = OpenHelper.getUserId();

        OrderDetails orderDetails = new OrderDetails();

        orderDetails.setProductId(vipType.getVipTypeId());
        orderDetails.setOrderId(orderInfo.getOrderId());
        orderDetails.setEvaluatedState(CommonConstants.DISABLED);
        orderDetails.setAfterSaleState(CommonConstants.DISABLED);
        orderDetails.setUserId(userId);
        orderDetails.setProductPrice(vipType.getPrePrice());
        orderDetails.setProductImages(vipType.getVipLogo());
        orderDetails.setProductAmount(vipType.getPrePrice());
        orderDetails.setProductTitle(vipType.getVipName());

        return orderDetails;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        OrderDetails orderDetails = orderDetailsService.getOne(new QueryWrapper<OrderDetails>().lambda().eq(OrderDetails::getOrderId, result.getLong("orderId")));
        DateTime offsetMinute = DateUtil.offsetMinute(result.get("createTime"), 30);
        result.put("offsetMinute", offsetMinute);
        result.put("orderDetails", orderDetails);
    }

    public ResultBody confirm(Map params, String couponUserIds) {
        EntityMap result = new EntityMap();
        Long userId = OpenHelper.getUserId();
        BigDecimal totalAmount = new BigDecimal("0");
        BigDecimal totalFreight = new BigDecimal("0");
        BigDecimal totalCouponAmount = new BigDecimal("0");
        Integer totalNum = 0;


        BigDecimal payAmount = totalAmount.add(totalFreight).subtract(totalCouponAmount);
        if (FlymeUtils.ltzero(payAmount)) {
            payAmount = new BigDecimal("0.01");
        }

        result.put("totalAmount", totalAmount);
        result.put("totalFreight", totalFreight);
        result.put("payAmount", payAmount);
        result.put("totalNum", totalNum);
        result.put("couponUserIds", couponUserIds);
        result.put("totalCouponAmount", totalCouponAmount);
        return ResultBody.ok(result);
    }




    public OrderInfo findByOrderNo(String orderNo) {
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.eq(true, "orderNo", orderNo);
        return (OrderInfo) this.getOne(cq);
    }


    @Transactional
    @Override
    public Boolean paySuccess(String outTradeNo, Map<String, Object> context, Integer orderState) {
        OrderInfo orderInfo = this.findByOrderNo(outTradeNo);
        if (FlymeUtils.isNotEmpty(orderInfo)) {
            Integer payStatus = orderInfo.getPayState();
            Integer orderType = FlymeUtils.getInteger(orderInfo.getOrderType(), 1);
            Integer parentOrder = FlymeUtils.getInteger(orderInfo.getParentOrder(), 0);
            String payTime = DateUtils.getDateTime();
            UpdateWrapper update;
            if (payStatus.equals(PayStatusEnum.NOPAY.getCode())) {
                update = new UpdateWrapper();
                update.set(true, "payState", PayStatusEnum.PAY.code);
                update.set(true, "payTime", payTime);
                update.set(true, "orderState", orderState);
                update.set(true, "payType", context.get("payType"));
                update.eq(true, "orderId", orderInfo.getOrderId());
                if (parentOrder.equals(CommonConstants.ENABLED)) {
                    update.set(true, "showState", CommonConstants.DISABLED);
                }

                this.update(update);
                if (orderType.equals(1)) {
                    ProdProduct product = this.productService.getById(detailsMapper.selectOne(new QueryWrapper<OrderDetails>().eq("orderId", orderInfo.getOrderId())).getProductId());
                    busProductService.updateSaleCount(product.getProductId(), product.getSaleCount() + 1);
                    // TODO 测试 不走付款计算佣金
                    EntityMap payUser = appUserService.getAppUserVipInfo(orderInfo.getUserId());
                    EntityMap superiorUser = ObjectUtil.isEmpty(payUser.get("inviterId")) ? null : appUserService.getAppUserVipInfo(payUser.getLong("inviterId"));
                    rebateLogicService.buyCommodity(orderInfo, product, payUser, superiorUser);

                }
            }

        }

        return true;
    }

    private OrderDetails getOrderDetails(OrderInfo parentOrder, OrderInfo orderInfo, ProdProduct product) {
        Long userId = OpenHelper.getUserId();

        OrderDetails orderDetails = new OrderDetails();
        orderDetails.setProductId(product.getProductId());
        if (FlymeUtils.isNotEmpty(parentOrder)) {
            orderDetails.setParentOrderId(parentOrder.getOrderId());
        }
        orderDetails.setSkuTitle(product.getProductSeries());
        orderDetails.setOrderId(orderInfo.getOrderId());
        orderDetails.setEvaluatedState(CommonConstants.DISABLED);
        orderDetails.setAfterSaleState(CommonConstants.DISABLED);
        orderDetails.setUserId(userId);
        orderDetails.setProductPrice(product.getProductPrice());
        orderDetails.setProductNum(product.getSaleCount() + 1);
        orderDetails.setProductImages(product.getCoverImage());
        orderDetails.setProductAmount(product.getProductPrice());
        orderDetails.setProductTitle(product.getProductName());

        return orderDetails;
    }





    private void initOrderInfo(OrderInfo orderInfo, BigDecimal payAmount, Long userId, BigDecimal totalAmount) {
        orderInfo.setPayAmount(payAmount);
        //下单人
        orderInfo.setUserId(userId);
        orderInfo.setOrderNo(orderNoUtil.getOrderNo());
        //未删除
        orderInfo.setDeleted(CommonConstants.DEL_NO);
        orderInfo.setDiscountAmount(new BigDecimal("0"));
        //待付款
        orderInfo.setOrderState(OrderStatusEnum.UNPAY.getCode());
        //默认展示,如有拆分则修改为母单
        orderInfo.setShowState(CommonConstants.INT_1);
        //订单总金额
        orderInfo.setTotalAmount(totalAmount);
        orderInfo.setShopScore(CommonConstants.INT_0);
        //未支付
        orderInfo.setPayState(PayStatusEnum.NOPAY.getCode());
    }

    @Override
    public ResultBody getPayParams(Long orderId) {
        return ResultBody.ok(MapUtil.empty());
    }

    @Override
    public Long getCountByYearAndUserId(int years, Long userId) {
        return baseMapper.selectCount(new QueryWrapper<OrderInfo>().eq("userId", userId).eq("DATE_FORMAT(createTime, '%Y')", years));
    }

    @Override
    public void saveVipOrder(Long vipTypeId, Long userId, String outTradeNo, Object transaction_id) {
        VipType vipType = this.vipTypeService.getById(vipTypeId);
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setPayAmount(vipType.getPrePrice());
        //下单人
        orderInfo.setUserId(userId);
        orderInfo.setOrderNo(outTradeNo);
        //未删除
        orderInfo.setDeleted(CommonConstants.DEL_NO);
        orderInfo.setDiscountAmount(new BigDecimal("0"));
        //待付款
        orderInfo.setOrderState(OrderStatusEnum.FINISHED.getCode());
        //默认展示,如有拆分则修改为母单
        orderInfo.setShowState(CommonConstants.INT_1);
        //订单总金额
        orderInfo.setTotalAmount(vipType.getPrePrice());
        orderInfo.setShopScore(CommonConstants.INT_0);
        //未支付
        orderInfo.setPayState(PayStatusEnum.PAY.getCode());

        orderInfo.setOrderTitle(vipType.getVipName());
        orderInfo.setOrderType(2);
        this.save(orderInfo);
        orderDetailsService.save(getOrderDetails(orderInfo, vipType));

    }
}
